import React, {FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import "../css/DetailsContent.less";
import {loadMenuChild, loadVirtualMenu, openEditUrl} from "../../services/MenuService.tsx";
import {importComponent, isArray, isDevelopment, isFunction, strToObject, tryFunction} from "../../utils";
import {AxiosSer} from "../../services/HttpService.tsx";
import {Menu} from "antd";
import {getLocale} from "../../../i18n/i18n.tsx";
import {useTranslation} from "react-i18next";
import {useParams} from "react-router";
import {GlobalErr} from "../../global/GlobalErr.tsx";
import useStateRef from "../../customUse/useStateRef.tsx";
import {coreConnect} from "../../utils/StoreUtil.tsx";

interface DetailsContentProps {
    key?: string,
    menuMap: any,
    row?: any,
    url: string,
    title: string,
    objectId: string,
    objectName: string,
    objectTypeId: string,
    objectStatusId: string,
    keywords: string,
    queryMethod: string,
    queryParams: any,
    ds: any,
    init: any,
    dispatch: Function,
    comProps: any
}

const DetailsContent: FC<DetailsContentProps> = (props) => {
    const {t} = useTranslation();
    const urlParams = useParams();
    const objectDataRef = useRef({})
    const comRef = useRef(undefined)
    const [objectData, setObjectData] = useStateRef({}, objectDataRef),
        [menu, setMenu] = useState<any>(),
        [selectMenu, setSelectMenu] = useState<any>();

    const onSelect = useCallback(({item, key}) => {
        setSelectMenu({
            key: key,
            label: getLocale(item.props.labelCn, item.props.labelEn, item.props.labelPt),
            labelCn: item.props.labelCn,
            labelEn: item.props.labelEn,
            labelPt: item.props.labelPt,
            dom: item.props.dom,
            comProp: item.props.comProp
        })
    }, []);

    const loadObjectData = useCallback(async () => {
        let {objectId, queryMethod = "get", queryParams = {}, row = {}} = {...urlParams, ...props};
        let newObjectData = {};
        if (objectId === "undefined") {
            objectId = "";
        }
        if (!props.url) {
            newObjectData = {id: objectId, ...queryParams};
        } else {
            const {data, code, msg} = await AxiosSer(props.url, queryMethod, {
                ...queryParams,
                id: objectId
            });
            if (code !== "1") {
                props.ds.closeSplitPage && props.ds.closeSplitPage()
                return
            }
            newObjectData = isArray(data) ? data[0] : data;
        }
        setObjectData({id: objectId, ...queryParams, ...row, ...newObjectData});
    }, [props.url, props.row, props.queryMethod, props.objectId, props.queryParams]);

    const loadDetailsMenu = useCallback(async () => {
        const {objectTypeId, objectStatusId, row = {}, menuId} = {...urlParams, ...props};
        let newMenu;
        if (objectTypeId) {
            newMenu = (await loadVirtualMenu({objectTypeName: objectTypeId, objectStatusId, menuType: "MENU"}))[0];
        } else if (menuId) {
            newMenu = (await loadMenuChild({parentId: menuId, menuType: "MENU"}))[0];
        } else {
            return
        }
        if (newMenu.subassembly) {
            newMenu.dom = await importComponent(newMenu.subassembly);
            newMenu.comProp = {...props, ...strToObject(newMenu.operate)};
        } else if (newMenu.children && newMenu.children.length) {
            const menus = [], menuKey = objectTypeId + "-" + objectStatusId;
            let defaultSelectMenu;
            for (let i = 0; i < newMenu.children.length; i++) {
                const node = newMenu.children[i];
                let menuConfig = {}, isReturn = true;
                if (node.config) {
                    tryFunction(() => {
                        eval("window.menuConfig =" + node.config)
                        menuConfig = window.menuConfig || {};
                    });
                    if (isFunction(menuConfig.isShow)) {
                        isReturn = menuConfig.isShow({...props, row: {...row, ...objectDataRef.current}} || {})
                    }
                }
                let comProp = node.operate ? strToObject(node.operate) : {};
                if (!node.subassembly) {
                    comProp.errContent = (<div>
                                <span className={"sf_core_link"} onClick={() => {
                                    openEditUrl(node.id)
                                }}>{node.id}</span>
                        <span>{t("unComPath")}</span>
                    </div>);
                }
                const newNode = {
                    key: node.id,
                    label: getLocale(node.zhCn, node.usEn, node.ptBr),
                    labelCn: node.zhCn,
                    labelEn: node.usEn,
                    labelPt: node.ptBr,
                    dom: node.subassembly ? await importComponent(node.subassembly) : GlobalErr,
                    comProp: comProp,
                }
                if (props.menuMap && props.menuMap[menuKey] && node.id === props.menuMap[menuKey]) {
                    defaultSelectMenu = newNode
                }
                isReturn && menus.push(newNode);
            }
            newMenu = menus;
            setSelectMenu(defaultSelectMenu || newMenu[0]);
        } else {
            newMenu = undefined;
        }
        setMenu(newMenu);
    }, [props.objectTypeId, props.row, props.objectStatusId, props.menuMap]);

    const init = useCallback(async () => {
        await loadObjectData()
        await loadDetailsMenu()
    }, [props.objectId, props.row, props.objectStatusId])

    useEffect(() => {
        init()
    }, [props.objectId, props.row, props.objectStatusId]);


    useEffect(() => {
        if (selectMenu) {
            const {objectTypeId, objectStatusId} = props;
            const key = objectTypeId + "-" + objectStatusId;
            props.dispatch({
                type: "detailMenuReducer/addMap",
                payload: {
                    key: key,
                    value: selectMenu.key
                }
            });
        }
    }, [selectMenu]);

    useImperativeHandle(props.init, () => {
        return {
            comRef: comRef.current
        };
    });

    const renderCom = useMemo(() => {
        if (!menu || !objectData) {
            return null
        }
        const Com = menu.dom;
        return (
            <div className="sf_core_drawer_info_content">
                <Com init={comRef} menuId={menu.id} {...menu.comProp} row={objectData} keywords={props.keywords}/>
            </div>
        );

    }, [menu, objectData, props.keywords]);

    const renderMenuCom = useMemo(() => {
        if (!menu || !selectMenu || !objectData) {
            return null
        }
        const Com = selectMenu.dom;
        return (
            <div style={{width: "100%", height: "100%"}}>
                <div className="sf_core_drawer_info_menu">
                    <Menu mode="horizontal" items={menu} onSelect={onSelect} selectedKeys={[selectMenu.key]}
                          onClick={({key, domEvent}) => {
                              if (domEvent.altKey && isDevelopment()) {
                                  openEditUrl(key)
                                  return
                              }
                          }}/>
                </div>
                <div className="sf_core_drawer_info_content" style={{height: "calc(100% - 36px)"}}>
                    <Com init={comRef} menuId={selectMenu.key} {...selectMenu.comProp} row={objectData}
                         key={selectMenu.key}
                         keywords={props.keywords}/>
                </div>
            </div>
        )
    }, [menu, selectMenu, objectData, props.keywords]);

    const renderDetailsContent = useMemo(() => {
        if (!menu || !objectData) {
            return null
        }
        return (
            <div className="sf_core_drawer_info">
                {menu.dom ? renderCom : renderMenuCom}
            </div>
        )
    }, [menu, selectMenu, objectData, props.key, props.ds, props.keywords]);

    return (renderDetailsContent);
};
export default coreConnect("detailMenuReducer")(React.memo(DetailsContent));
